home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
workbench
/
tools
/
czesc_2
/
ispell-3.3ljr
/
ispell
/
ispell.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-08
|
36KB
|
1,814 lines
/*
* ispell.c - An interactive spelling corrector.
*
* Copyright (c), 1983, by Pace Willisson
* Permission for non-profit use is hereby granted.
* All other rights reserved.
*
* 1987, Robert McQueer, added:
* -w option & handling of extra legal word characters
* -d option for alternate dictionary file
* -p option & WORDLIST variable for alternate personal dictionary
* -x option to suppress .bak files.
* 8 bit text & config.h parameters
* 1987, Geoff Kuenning, added:
* -c option for creating suffix suggestions from raw words
* suffixes in personal dictionary file
* hashed personal dictionary file
* -S option for unsorted word lists
* 1987, Greg Schaffer, added:
* -T option (for TeX and LaTeX instead of troff) [later changed to -t]
* passes over \ till next whitespace.
* does not recognize % (comment)
* 1989, Tomas Rokicki, added:
* ispell'local'words to indicate rest of line for local words
* -L option to write local words when done
* fixed `sleep' so some error messages could be seen.
* 1989, Loren J. Rittle, added:
* Fixed ISpell to use proper STDOUT/STDIN streams when used in
* non-interactive modes.
* ARexx Server Mode, invoke with -r option ( for rexx )
* Thanks to Tomas Rokicki for MinRexx! and example code.
* 1990, Loren J. Rittle, reworked:
* Converted to SAS/C v5.10.
* Added full prototype checking.
* Fixed more bugs, many memory related.
* Finally left UNIX behind completely.
* Got rid of alot of (what I would call) kludge code, left
* over from the original port job. See amiga.c for more details.
* 1991, Loren J. Rittle, added:
* many new ARexx Server Mode commands.
* released to the world.
* 1992, W.G.J. Langeveld, added:
* -R switch, same as -r, but prints out line numbers and column numbers
* during "filecheck".
* 1992, Loren J. Rittle, reworked:
* Converted to SAS/C v6.0.
* Reworked W.G.J. Langeveld's '-R' switch to make new ARexx interface
* point instead of startup time option. Once again, '-r' is the only
* server mode provided by ispell.
*/
#undef _STRICT_ANSI
#include <stdio.h>
#define _STRICT_ANSI
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
extern int creat (char *, int);
#pragma msg 148 ignore push
#pragma msg 149 ignore push
#pragma msg 61 ignore push
#include <dos/dos.h>
#pragma msg 149 pop
#pragma msg 61 pop
#include "config.h"
#include "ispell.h"
#include "version.h"
struct rexxCommandList rcl[] =
{
{"add", &rexxadd},
{"quickadd", &rexxquickadd},
{"check", &rexxcheck},
{"quickcheck", &rexxquickcheck},
{"lookup", &rexxlookup},
{"filecheck", &rexxfilecheck},
{"extendedfilecheck", &rexxextendedfilecheck},
{"version", &rexxversion},
{"exit", &rexxexit},
{NULL, NULL}
};
SHORT KeepGoing = TRUE; /* main loop control value */
char rootword[BUFSIZ];
struct dent *lastdent;
char *hashstrings;
struct hashheader hashheader;
char tempfile[200];
#define ISTEXTERM(c) (((c) == '{') || \
((c) == '}') || \
((c) == '[') || \
((c) == ']'))
int li, co; /* lines, columns */
FILE *infile;
FILE *outfile;
char hashname[MAXPATHLEN];
/*
** we use extended character set range specifically to allow intl.
** character set characters. We are being REALLY paranoid about indexing
** this array - explicitly cast into unsigned INTEGER, then mask
** If NO8BIT is set, text will be masked to ascii range.
*/
static int Trynum;
#ifdef NO8BIT
static char Try[128];
static char Checkch[128];
#define iswordch(X) (Checkch[((unsigned)(X))&0x7f])
#else
static char Try[256];
static char Checkch[256];
#define iswordch(X) (Checkch[((unsigned)(X))&0xff])
#endif
static int sortit = 1;
void givehelp (void)
{
erase ();
printcon (Version_ID);
printcon ("\n");
printcon ("Whenever a word is found that is not in the dictionary,\n");
printcon ("it is printed on the first line of the screen. If the dictionary\n");
printcon ("contains any similar words, they are listed with a single digit\n");
printcon ("next to each one. You have the option of replacing the word\n");
printcon ("completely, or choosing one of the suggested words.\n");
printcon ("\n");
printcon ("Commands are:\n\n");
printcon ("R Replace the misspelled word completely.\n");
printcon ("Space Accept the word this time only\n");
printcon ("A Accept the word for the rest of this file.\n");
printcon ("I Accept the word, and put it in your private dictionary.\n");
printcon ("0-9 Replace with one of the suggested words.\n");
printcon ("L Look up words via regular expression.\n");
printcon ("Q Write the rest of this file, ignoring misspellings, ");
printcon ("and start next file.\n");
printcon ("X Exit immediately. Asks for confirmation. ");
printcon ("Leaves file unchanged.\n");
printcon ("^L Redraw screen.\n");
printcon ("\n\n");
printcon ("-- Type space to continue --");
while (getccon () != ' ')
;
}
int cflag = 0;
int lflag = 0;
int incfileflag = 0;
int aflag = 0;
int fflag = 0;
int sflag = 0;
int xflag = 0;
int tflag = 0;
int llflag = 0;
int rflag = 0;
/*
* Willy's flag: for more extended spell-file capability
*/
int wflag = 0;
#define MAXPOSSIBLE 100 /* Max no. of possibilities to generate */
char possibilities[MAXPOSSIBLE][BUFSIZ];
int pcount;
int maxposslen;
char *askfilename;
static char *Cmd;
void usage (void)
{
fprintf (stderr,
"Usage: %s [-dfile | -pfile | -wchars | -t | -x | -S] file .....\n",
Cmd);
fprintf (stderr,
" %s -r\n",
Cmd);
fprintf (stderr,
" %s [-dfile | -pfile | -wchars] -l\n",
Cmd);
fprintf (stderr,
" %s [-dfile | -pfile | -ffile | -s] {-a | -A}\n",
Cmd);
fprintf (stderr, " %s [-wchars] -c\n", Cmd);
fprintf (stderr, " %s -v\n", Cmd);
exit (1);
}
static void initckch (void)
{
register int c;
Trynum = 0;
#ifdef NO8BIT
for (c = 0; c < 128; ++c)
{
#else
for (c = 0; c < 256; ++c)
{
#endif
if (myalpha ((char) c))
{
Checkch[c] = (char) 1;
if (myupper ((char) c))
{
Try[Trynum] = (char) c;
++Trynum;
}
}
else
Checkch[c] = (char) 0;
}
}
void main (int argc, char **argv)
{
char *p;
char *cpd;
char num[4];
unsigned mask;
static char outbuf[BUFSIZ];
Cmd = *argv;
initckch ();
sprintf (hashname, "%s%s", LIBDIR, DEFHASH);
cpd = NULL;
argv++;
argc--;
while (argc && **argv == '-')
{
switch ((*argv)[1])
{
case 'r':
rflag++;
lflag++;
break;
case 'v':
printf ("%s\n", Version_ID);
exit (0);
case 't':
tflag++;
break;
case 'A':
incfileflag = 1;
aflag = 1;
break;
case 'a':
aflag++;
break;
case 'c':
cflag++;
lflag++;
break;
case 'x':
xflag++;
break;
case 'f':
fflag++;
p = (*argv) + 2;
if (*p == '\0')
{
argv++;
argc--;
if (argc == 0)
usage ();
p = *argv;
}
askfilename = p;
break;
case 'l':
lflag++;
break;
case 'L':
llflag++;
break;
case 's':
sflag++;
break;
case 'S':
sortit = 0;
break;
case 'p':
cpd = (*argv) + 2;
if (*cpd == '\0')
{
argv++;
argc--;
if (argc == 0)
usage ();
cpd = *argv;
}
break;
case 'd':
p = (*argv) + 2;
if (*p == '\0')
{
argv++;
argc--;
if (argc == 0)
usage ();
p = *argv;
}
if (*p == '/')
strcpy (hashname, p);
else
sprintf (hashname, "%s%s", LIBDIR, p);
break;
case 'w':
num[3] = '\0';
#ifdef NO8BIT
mask = 0x7f;
#else
mask = 0xff;
#endif
p = (*argv) + 2;
if (*p == '\0')
{
argv++;
argc--;
if (argc == 0)
usage ();
p = *argv;
}
while (Trynum <= mask && *p != '\0')
{
if (*p != 'n' && *p != '\\')
{
Checkch[((unsigned) (*p)) & mask] = (char) 1;
Try[Trynum] = *p & mask;
++p;
}
else
{
++p;
num[0] = '\0';
num[1] = '\0';
num[2] = '\0';
num[3] = '\0';
if (isdigit (p[0]))
num[0] = p[0];
if (isdigit (p[1]))
num[1] = p[1];
if (isdigit (p[2]))
num[2] = p[2];
if (p[-1] == 'n')
{
p += strlen (num);
num[0] = atoi (num);
}
else
{
p += strlen (num);
if (num[0])
num[0] -= '0';
if (num[1])
{
num[0] <<= 3;
num[0] += num[1] - '0';
}
if (num[2])
{
num[0] <<= 3;
num[0] += num[2] - '0';
}
}
Try[Trynum] = num[0] & mask;
Checkch[num[0] & mask] = 1;
}
++Trynum;
}
break;
default:
usage ();
}
argv++;
argc--;
}
if (!argc && !lflag && !aflag && !rflag)
usage ();
if (linit () < 0)
exit (0);
treeinit (cpd);
if (rflag)
{
servermode ();
exit (0);
}
if (aflag)
{
askmode ();
exit (0);
}
setbuf (stdout, outbuf);
if (lflag)
{
infile = stdin;
checkfile ();
exit (0);
}
terminit ();
while (argc--)
dofile (*argv++);
done ();
}
char firstbuf[BUFSIZ], secondbuf[BUFSIZ];
char *currentchar;
char token[BUFSIZ];
int quit;
char *currentfile = NULL;
void dofile (char *filename)
{
int c;
char bakfile[256];
char *cp;
currentfile = filename;
if ((infile = fopen (filename, "r")) == NULL)
{
fprintf (stderr, "Can't open %s\n", filename);
sleep (2);
return;
}
if (access (filename, 2) < 0)
{
fprintf (stderr, "Can't write to %s\n", filename);
sleep (2);
return;
}
tmpnam (tempfile);
if ((outfile = fopen (tempfile, "w")) == NULL)
{
fprintf (stderr, "Can't create %s\n", tempfile);
sleep (2);
return;
}
quit = 0;
/* See if the file is a .tex file. If so, set the appropriate flag. */
if ((cp = strrchr (filename, '.')) != NULL && strcmp (cp, ".tex") == 0)
tflag = 1;
checkfile ();
fclose (infile);
fclose (outfile);
if (!cflag)
treeoutput ();
if ((infile = fopen (tempfile, "r")) == NULL)
{
fprintf (stderr, "temporary file disappeared (%s)\n", tempfile);
sleep (2);
return;
}
sprintf (bakfile, "%s%s", filename, BAKEXT);
remove (bakfile);
if (rename (filename, bakfile))
{
fprintf (stderr, "can't rename %s to %s\n", filename, bakfile);
sleep (2);
return;
}
/* if we can't write new, preserve .bak regardless of xflag */
if ((outfile = fopen (filename, "w")) == NULL)
{
fprintf (stderr, "can't create %s\n", filename);
sleep (2);
return;
}
while ((c = getc (infile)) != EOF)
putc (c, outfile);
fclose (infile);
fclose (outfile);
remove (tempfile);
if (xflag)
remove (bakfile);
}
struct RexxMsg *RexxMsg;
void checkfile (void)
{
register char *p;
register int len;
int addflag;
int count = 0;
/*
* Willy's mod: keep track of line number
*/
long linenum = 0;
secondbuf[0] = 0;
while (1)
{
strcpy (firstbuf, secondbuf);
if (quit)
{ /* quit can't be set in l mode */
while (fgets (secondbuf, sizeof secondbuf, infile) != NULL)
fputs (secondbuf, outfile);
break;
}
if (fgets (secondbuf, sizeof secondbuf, infile) == NULL)
break;
/*
* Willy's mod: keep track of line number
*/
linenum++;
currentchar = secondbuf;
addflag = 0;
len = strlen (secondbuf) - 1;
if (!tflag)
{
/* skip over .if */
if (strncmp (currentchar, ".if t", 5) == 0
|| strncmp (currentchar, ".if n", 5) == 0)
{
copyout (¤tchar, 5);
while (*currentchar && isspace (*currentchar))
copyout (¤tchar, 1);
}
/* skip over .ds XX or .nr XX */
if (strncmp (currentchar, ".ds ", 4) == 0
|| strncmp (currentchar, ".de ", 4) == 0
|| strncmp (currentchar, ".nr ", 4) == 0)
{
copyout (¤tchar, 3);
while (*currentchar && isspace (*currentchar))
copyout (¤tchar, 1);
while (*currentchar && !isspace (*currentchar))
copyout (¤tchar, 1);
if (*currentchar == 0)
{
if (!lflag)
putc ('\n', outfile);
continue;
}
}
}
if (secondbuf[len] == '\n')
secondbuf[len] = 0;
/* if this is a formatter command, skip over it */
if (!tflag && *currentchar == '.')
{
while (*currentchar && !myspace (*currentchar))
{
if (!lflag)
putc (*currentchar, outfile);
currentchar++;
}
if (*currentchar == 0)
{
if (!lflag)
putc ('\n', outfile);
continue;
}
}
while (1)
{
while (*currentchar && !iswordch (*currentchar))
{
if (tflag) /* TeX or LaTeX stuff */
{
if (*currentchar == '\\')
{
/* skip till whitespace */
while (*currentchar &&
(!isspace (*currentchar) &&
!ISTEXTERM (*currentchar)))
{
if (!lflag)
putc (*currentchar, outfile);
currentchar++;
}
continue;
}
}
else
{
/* formatting escape sequences */
if (*currentchar == '\\')
{
switch (currentchar[1])
{
case 'f':
if (currentchar[2] != '(')
{
/* font change: \fX */
copyout (¤tchar, 3);
}
else
{
/* font change: \f(XY */
copyout (¤tchar, 5);
}
continue;
case 's':
/* size change */
p = currentchar + 2;
if (*p == '+' || *p == '-')
p++;
/* This looks wierd 'cause we assume
** *p is now a digit.
*/
if (isdigit (p[1]))
p++;
copyout (¤tchar,
p - currentchar + 1);
continue;
case '(':
/* extended char set escape: \(XX */
copyout (¤tchar, 4);
continue;
case '*':
if (currentchar[2] != '(')
copyout (¤tchar, 3);
else
copyout (¤tchar, 5);
continue;
default:
break;
}
}
}
if (!lflag)
putc (*currentchar, outfile);
currentchar++;
}
if (*currentchar == 0)
break;
p = token;
while (iswordch (*currentchar) ||
(*currentchar == '\'' &&
iswordch (*(currentchar + 1))))
*p++ = *currentchar++;
*p = 0;
/*
* mods by tom rokicki to handle local document words automagically
*/
if (token[0] == 'i' &&
strcmp (token, "ispell'local'words") == 0)
{
addflag = 1;
}
else
{
if (addflag)
{
if (!good (token))
{
treeinsert (token, 0);
}
}
if (lflag)
{
if (!good (token) && !cflag)
if (rflag) {
/*
* Willy's mod: if wflag, print out word, line number and colum
*/
if (wflag) {
static char var[64];
static char value[64];
sprintf (value, "%d", ++count);
SetRexxVar (RexxMsg, "ISPELLRESULT.COUNT", value, strlen (value));
sprintf (var,"ISPELLRESULT.%d.WORD", count);
SetRexxVar (RexxMsg, var, token, strlen (token));
sprintf (value, "%d", linenum);
sprintf (var,"ISPELLRESULT.%d.LINE", count);
SetRexxVar (RexxMsg, var, value, strlen (value));
sprintf (value, "%d", currentchar - secondbuf - strlen(token) + 1);
sprintf (var,"ISPELLRESULT.%d.COLUMN", count);
SetRexxVar (RexxMsg, var, value, strlen (value));
}
else {
fprintf (outfile, "%s\n", token);
}
}
else
fprintf (stdout, "%s\n", token);
}
else
{
if (!quit)
correct (token, ¤tchar);
}
}
if (!lflag)
fprintf (outfile, "%s", token);
}
if (!lflag)
putc ('\n', outfile);
}
if (llflag)
{
lldump ();
}
}
void correct (char *token, char **currentchar)
{
register int c;
register int i;
int col_ht;
int ncols;
char *start_l2;
char *begintoken;
begintoken = *currentchar - strlen (token);
checkagain:
if (good (token))
return;
erase ();
printcon (" %s", token);
if (currentfile)
printcon (" File: %s", currentfile);
printcon ("\n\n");
makepossibilities (token);
/*
* Make sure we have enough room on the screen to hold the
* possibilities. Reduce the list if necessary. co / (maxposslen + 8)
* is the maximum number of columns that will fit.
*/
col_ht = li - 6; /* Height of columns of words */
ncols = co / (maxposslen + 8);
if (pcount > ncols * col_ht)
pcount = ncols * col_ht;
#ifdef EQUAL_COLUMNS
/*
* Equalize the column sizes. The last column will be short.
*/
col_ht = (pcount + ncols - 1) / ncols;
#endif
for (i = 0; i < pcount; i++)
{
move (2 + (i % col_ht), (maxposslen + 8) * (i / col_ht));
printcon ("%2d: %s", i, possibilities[i]);
}
move (li - 3, 0);
show_line (firstbuf, firstbuf, 0);
start_l2 = secondbuf;
if (line_size (secondbuf, *currentchar) > co - 1)
{
start_l2 = begintoken - (co / 2);
while (start_l2 < begintoken)
{
i = line_size (start_l2, *currentchar) + 1;
if (i <= co)
break;
start_l2 += i - co;
}
if (start_l2 > begintoken)
start_l2 = begintoken;
if (start_l2 < secondbuf)
start_l2 = secondbuf;
}
show_line (start_l2, begintoken, strlen (token));
while (1)
{
switch (c = (getccon () & NOPARITY))
{
case 'Z' & 037:
stop ();
erase ();
goto checkagain;
case ' ':
erase ();
return;
case 'x':
case 'X':
printcon ("Are you sure you want to throw away your changes? ");
c = (getccon () & NOPARITY);
if (c == 'y' || c == 'Y')
{
erase ();
done ();
}
putchar (7);
goto checkagain;
case 'i':
case 'I':
treeinsert (token, 1);
erase ();
return;
case 'a':
case 'A':
treeinsert (token, 0);
if (llflag)
llinsert (token);
erase ();
return;
case 'L' & 037:
goto checkagain;
case '?':
givehelp ();
goto checkagain;
case 'r':
case 'R':
move (li - 1, 0);
printcon ("Replace with: ");
if (getline (token) == NULL)
{
putccon (7);
erase ();
goto checkagain;
}
inserttoken (secondbuf, begintoken, token, currentchar);
erase ();
goto checkagain;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
i = c - '0';
if (pcount > 10
&& i > 0 && i <= (pcount - 1) / 10)
{
c = getccon () & NOPARITY;
if (c >= '0' && c <= '9')
i = i * 10 + c - '0';
else if (c != '\n')
{
putccon (7);
break;
}
}
if (i < pcount)
{
strcpy (token, possibilities[i]);
inserttoken (secondbuf, begintoken,
token, currentchar);
erase ();
return;
}
putccon (7);
break;
case '\r': /* This makes typing \n after single digits */
case '\n': /* ..less obnoxious */
break;
case 'l':
case 'L':
{
char buf[100];
move (li - 1, 0);
printcon ("Lookup string ('*' is wildcard): ");
if (getline (buf) == NULL)
{
putccon (7);
erase ();
goto checkagain;
}
printcon ("\n\n");
lookharder (buf);
erase ();
goto checkagain;
}
case 'q':
case 'Q':
quit = 1;
erase ();
return;
default:
putccon (7);
break;
}
}
}
void show_line (char *line, char *invstart, int invlen)
{
register int width;
width = 0;
while (line != invstart && width < co - 1)
width += show_char (*line++, width);
if (invlen)
{
inverse ();
while (--invlen >= 0 && width < co - 1)
width += show_char (*line++, width);
normal ();
}
while (*line && width < co - 1)
width += show_char (*line++, width);
printcon ("\n");
}
int show_char (int ch, int linew)
{
if (ch == '\t')
{
putccon ('\t');
return 8 - (linew & 0x07);
}
else if (ch < ' ')
{
putccon ('^');
putccon (ch + 'A' - '\001');
return 2;
}
putccon (ch);
return 1;
}
int line_size (char *buf, char *bufend)
{
register int width;
for (width = 0; buf < bufend && *buf; buf++)
{
if (*buf == '\t')
width = (width + 8) & ~0x07;
else if (*buf < ' ')
width += 2;
else
width++;
}
return width;
}
void inserttoken (char *buf, char *start, char *token, char **currentchar)
{
char copy[BUFSIZ];
register char *p, *q;
strcpy (copy, buf);
for (p = buf, q = copy; p != start; p++, q++)
*p = *q;
q += *currentchar - start;
while (*token && iswordch (*token))
*p++ = *token++;
*currentchar = p;
if (*token)
{
/*
** The token changed to two words. Split it up and save the
** second one for later.
*/
*p++ = *token;
*token++ = '\0';
while (*token)
*p++ = *token++;
}
while (*p++ = *q++)
;
}
int casecmp (char *a, char *b)
{
register char *ap;
register char *bp;
for (ap = a, bp = b; *ap; ap++, bp++)
{
if (mylower (*ap))
{
if (mylower (*bp))
{
if (*ap != *bp)
return *ap - *bp;
}
else
{
if (toupper (*ap) != *bp)
return toupper (*ap) - *bp;
}
}
else
{
if (myupper (*bp))
{
if (*ap != *bp)
return *ap - *bp;
}
else
{
if (tolower (*ap) != *bp)
return tolower (*ap) - *bp;
}
}
}
if (*bp != '\0')
return -((int)*bp);
return strcmp (a, b);
}
void makepossibilities (char *word)
{
register int i;
for (i = 0; i < MAXPOSSIBLE; i++)
possibilities[i][0] = 0;
pcount = 0;
maxposslen = 0;
#ifdef CAPITALIZE
wrongcapital (word);
#endif
if (pcount < MAXPOSSIBLE)
wrongletter (word);
if (pcount < MAXPOSSIBLE)
extraletter (word);
if (pcount < MAXPOSSIBLE)
missingletter (word);
if (pcount < MAXPOSSIBLE)
transposedletter (word);
if (sortit && pcount)
qsort ((char *) possibilities, pcount,
sizeof (possibilities[0]), casecmp);
}
int insert (char *word)
{
register int i;
for (i = 0; i < pcount; i++)
if (strcmp (possibilities[i], word) == 0)
return (0);
strcpy (possibilities[pcount++], word);
i = strlen (word);
if (i > maxposslen)
maxposslen = i;
if (pcount >= MAXPOSSIBLE)
return (-1);
else
return (0);
}
#ifdef CAPITALIZE
int wrongcapital (char *word)
{
char newword[BUFSIZ];
/*
** All-uppercase is always legal. If the word matches, "ins_cap"
** will recapitalize it correctly.
*/
strcpy (newword, word);
upcase (newword);
if (good (newword))
return ins_cap (newword, word);
return 0;
}
#endif
void wrongletter (char *word)
{
register int i, j, c, n;
char newword[BUFSIZ];
n = strlen (word);
strcpy (newword, word);
#ifdef CAPITALIZE
upcase (newword);
#endif
for (i = 0; i < n; i++)
{
for (j = 0; j < Trynum; ++j)
{
newword[i] = Try[j];
if (good (newword))
{
if (ins_cap (newword, word) < 0)
return;
}
}
#ifdef CAPITALIZE
c = word[i];
if (islower (c))
newword[i] = toupper (c);
else
newword[i] = c;
#else
newword[i] = word[i];
#endif
}
}
void extraletter (char *word)
{
char newword[BUFSIZ];
register char *p, *s, *t;
if (strlen (word) < 3)
return;
for (p = word; *p; p++)
{
for (s = word, t = newword; *s; s++)
if (s != p)
*t++ = *s;
*t = 0;
#ifdef CAPITALIZE
if (good (upcase (newword)))
{
if (ins_cap (newword, word) < 0)
return;
}
#else
if (good (newword))
{
if (ins_cap (newword, word) < 0)
return;
}
#endif
}
}
void missingletter (char *word)
{
char newword[BUFSIZ];
register char *p, *r, *s, *t;
register int i;
for (p = word; p == word || p[-1]; p++)
{
for (s = newword, t = word; t != p; s++, t++)
*s = *t;
r = s++;
while (*t)
*s++ = *t++;
*s = 0;
for (i = 0; i < Trynum; ++i)
{
*r = Try[i];
#ifdef CAPITALIZE
if (good (upcase (newword)))
{
if (ins_cap (newword, word) < 0)
return;
}
#else
if (good (newword))
{
if (ins_cap (newword, word) < 0)
return;
}
#endif
}
}
}
void transposedletter (char *word)
{
char newword[BUFSIZ];
register int t;
register char *p;
strcpy (newword, word);
for (p = newword; p[1]; p++)
{
t = p[0];
p[0] = p[1];
p[1] = t;
#ifdef CAPITALIZE
if (good (upcase (newword)))
{
if (ins_cap (newword, word) < 0)
return;
}
#else
if (good (newword))
{
if (ins_cap (newword, word) < 0)
return;
}
#endif
t = p[0];
p[0] = p[1];
p[1] = t;
}
}
/* Insert one or more correctly capitalized versions of pattern */
int ins_cap (char *word, char *pattern)
{
static char newword[BUFSIZ];
register char *p;
char *psave;
register int wcount;
if (*word == 0)
return 0;
strcpy (newword, word);
#ifdef CAPITALIZE
if (lastdent->allcaps)
return insert (upcase (newword)); /* Uppercase required */
for (p = pattern; *p; p++)
if (mylower (*p))
break;
if (*p == '\0')
return insert (upcase (newword)); /* Pattern was all caps */
for (p = pattern; *p; p++)
if (myupper (*p))
break;
if (*p == '\0')
{ /* Pattern was all lower */
if (!lastdent->followcase && !lastdent->capitalize)
return insert (lowcase (newword));
/*
** If there's a followcase version that's all-lower,
** insert only that version.
*/
if (lastdent->followcase)
{
p = lastdent->word;
p += strlen (p) + 1;
wcount = (*p++ & 0xFF);
while (--wcount >= 0)
{
for (psave = ++p;
*p && !myupper (*p);
p++)
;
if (*p == '\0') /* Was it all lowercase? */
return insert (psave); /* Yup, quit */
while (*p++)
; /* Skip to next case sample */
}
}
}
/*
** The sample wasn't all-upper, and either it wasn't all-lower or
** all-lower is illegal. Insert all legal capitalizations. In
** some cases, this may include all-lowercase.
*/
if (lastdent->capitalize)
{
lowcase (newword);
if (mylower (newword[0]))
newword[0] = toupper (newword[0]);
insert (newword);
}
if (lastdent->followcase)
{
p = lastdent->word;
p += strlen (p) + 1;
wcount = (*p++ & 0xFF);
while (--wcount >= 0)
{
/* Insert every variation; it's easier */
if (insert (++p) < 0)
return -1;
while (*p++)
; /* Skip to end of sample */
}
return 0;
}
if (lastdent->capitalize)
return 0;
/*
** We get here only if none of the special capitalization flags are
** set. If first letter of the pattern is capitalized, capitalize
** the first letter of the result. Otherwise produce all lowercase.
*/
lowcase (newword);
if (myupper (pattern[0]) && mylower (newword[0]))
newword[0] = toupper (newword[0]);
return insert (newword);
#else
if (myupper (pattern[0]))
{
if (myupper (pattern[1]))
{
for (p = word, q = newword; *p; p++, q++)
{
if (mylower (*p))
*q = toupper (*p);
else
*q = *p;
}
*q = 0;
}
else
{
if (mylower (word[0]))
newword[0] = toupper (word[0]);
else
newword[0] = word[0];
for (p = word + 1, q = newword + 1; *p; p++, q++)
if (myupper (*p))
*q = tolower (*p);
else
*q = *p;
*q = 0;
}
}
else
{
for (p = word, q = newword; *p; p++, q++)
if (myupper (*p))
*q = tolower (*p);
else
*q = *p;
*q = 0;
}
return insert (newword);
#endif
}
char *getline (char *s)
{
register char *p;
register int c;
p = s;
while (1)
{
c = (getccon () & NOPARITY);
if (c == '\\')
{
putccon ('\\');
c = (getccon () & NOPARITY);
backup ();
putccon (c);
*p++ = c;
}
else if (c == ('G' & 037))
{
return (NULL);
}
else if ((c == '\n') || (c == '\r'))
{
*p = 0;
return (s);
}
else if (c == '\b')
{
if (p != s)
{
p--;
backup ();
putccon (' ');
backup ();
}
}
else
{
*p++ = c;
putccon (c);
}
}
}
void servermode (void)
{
long rexxbit;
long returnbits;
rexxbit = upRexxPort ("IRexxSpell", rcl, NULL, &disp);
setbuf (stdin, NULL);
setbuf (stdout, NULL);
while (KeepGoing)
{
returnbits = Wait (rexxbit | SIGBREAKF_CTRL_C);
if (returnbits & SIGBREAKF_CTRL_C)
KeepGoing = 0;
if (returnbits & rexxbit)
dispRexxPort ();
}
/*
* With Rexx, we need to bring the port down. You might make this
* part of exit() for programs that have multiple paths to exit.
*/
dnRexxPort ();
}
/*
* Now we get into the actual code necessary for our REXX port; functions
* that do the real work. Note that this program was not structured
* particularly nicely for Rexx; I had to write each of these functions.
* Many programs have these subroutines already in place; they are called
* as part of the event loop. This progam, however, just has one big
* switch statement with different actions . . .
*
* First, our locals.
*/
/*
* This is our main dispatch function.
*/
void disp (struct RexxMsg *msg, struct rexxCommandList *dat, char *p)
{
(*(dat->userdata)) (msg, p);
}
/*
* This handler adds a word to the `global personal dictionary.'
*
* Now, in English, the word is added to whatever personal
* dictionary was found when ISpell was started up in ARexx
* server mode. (Under a multiuser system, we might want to
* restrict who can add words to this dictionary. For now
* we just do it! Yes, the AmigaOS is multiuser, hehe :-).
* No protection, the way true hackers like it, you (the
* user) get more rope to hang yourself :-), err the system
* with :-).
*/
void rexxadd (struct RexxMsg *msg, char *p)
{
if (*p)
treeinsert (p, 1);
treeoutput ();
replyRexxCmd (msg, 0L, 0L, "ok");
}
/*
* The quick version does not write the changes to disk.
* Useful if you will be adding many words. Be sure to
* call rexxadd at the end of the list (pass a null word,
* or a valid new word to be added).
*/
void rexxquickadd (struct RexxMsg *msg, char *p)
{
if (*p)
treeinsert (p, 1);
replyRexxCmd (msg, 0L, 0L, "ok");
}
/*
* This handler checks the spelling of a word.
*/
void rexxcheck (struct RexxMsg *msg, char *p)
{
char buf[512];
register int i;
if (good (p))
{
if (rootword[0] == 0)
strcpy (buf, "*");
else
sprintf (buf, "+ %s", rootword);
}
else
{
makepossibilities (p);
if (possibilities[0][0])
{
int bufend = 1;
int possibilitysize;
strcpy (buf, "&");
for (i = 0; i < MAXPOSSIBLE; i++)
{
if (possibilities[i][0] == 0)
break;
possibilitysize = strlen(possibilities[i]);
if ((possibilitysize + bufend) > 511)
break;
strcpy (&(buf[bufend++]), " ");
strcpy (&(buf[bufend]), possibilities[i]);
bufend += possibilitysize;
}
}
else
strcpy (buf, "#");
}
replyRexxCmd (msg, 0L, 0L, buf);
}
/*
* This handler checks the spelling of a word, it does
* not try to find replacement words as above. It only
* determines whether or not the word is in the dictoinary.
*/
void rexxquickcheck (struct RexxMsg *msg, char *p)
{
if (good (p))
replyRexxCmd (msg, 0L, 0L, "ok");
else
replyRexxCmd (msg, 0L, 0L, "bad");
}
void rexxlookup (struct RexxMsg *msg, char *p)
{
char buf[512];
char cmd[512];
char *rval;
int whence = 0;
int bufend = 1;
int lookupsize;
strcpy (buf, "&");
sprintf (cmd, "^%s$", p);
while ((rval = do_regex_lookup (cmd, whence++)) != NULL)
{
lookupsize = strlen(rval);
if ((lookupsize + bufend) > 511)
break;
strcpy (&(buf[bufend++]), " ");
strcpy (&(buf[bufend]), rval);
bufend += lookupsize;
}
replyRexxCmd (msg, 0L, 0L, buf);
}
/*
* This handler checks the spelling of a file.
*/
void rexxfilecheck (struct RexxMsg *msg, char *p)
{
char *cp;
currentfile = p;
if ((infile = fopen (p, "r")) == NULL)
{
replyRexxCmd (msg, 0L, 0L, "Error: Can't open input file");
return;
}
tmpnam (tempfile);
if ((outfile = fopen (tempfile, "w")) == NULL)
{
replyRexxCmd (msg, 0L, 0L, "Error: Can't open output file");
return;
}
quit = 0;
/* See if the file is a .tex file. If so, set the appropriate flag. */
if ((cp = strrchr (p, '.')) != NULL && strcmp (cp, ".tex") == 0)
tflag = 1;
else
tflag = 0;
lflag = 1;
checkfile ();
fclose (infile);
fclose (outfile);
replyRexxCmd (msg, 0L, 0L, tempfile);
}
/*
* This handler checks the spelling of a file using extended method.
*/
void rexxextendedfilecheck (struct RexxMsg *msg, char *p)
{
char *cp;
wflag = 1;
RexxMsg = msg;
currentfile = p;
if ((infile = fopen (p, "r")) == NULL)
{
replyRexxCmd (msg, 0L, 0L, "Error: Can't open input file");
return;
}
quit = 0;
/* See if the file is a .tex file. If so, set the appropriate flag. */
if ((cp = strrchr (p, '.')) != NULL && strcmp (cp, ".tex") == 0)
tflag = 1;
else
tflag = 0;
lflag = 1;
checkfile ();
fclose (infile);
replyRexxCmd (msg, 0L, 0L, "ok");
wflag = 0;
}
/*
* This handler returns the version of the program.
*/
void rexxversion (struct RexxMsg *msg, char *p)
{
char buf[512];
int bufend = strlen(Version_ID);
int namesize;
int i;
strcpy(buf, Version_ID);
buf[bufend++] = '\n';
for (i = 0; rcl[i].name != NULL; i++)
{
namesize = strlen(rcl[i].name);
if ((namesize + bufend) > 511)
break;
strcpy (&(buf[bufend++]), " ");
strcpy (&(buf[bufend]), rcl[i].name);
bufend += namesize;
}
replyRexxCmd (msg, 0L, 0L, buf);
}
/*
* This handler sets the exit flag.
*/
void rexxexit (struct RexxMsg *msg, char *p)
{
KeepGoing = 0;
replyRexxCmd (msg, 0L, 0L, "bye");
}
void askmode (void)
{
char buf[BUFSIZ];
register int i;
if (fflag)
{
if (freopen (askfilename, "w", stdout) == NULL)
{
fprintf (stderr, "Can't create %s\n", askfilename);
exit (1);
}
}
setbuf (stdin, NULL);
setbuf (stdout, NULL);
while (xgets (buf) != NULL)
{
/* *line is like `i', @line is like `a' */
if (buf[0] == '*' || buf[0] == '@')
{
treeinsert (buf + 1, buf[0] == '*');
fprintf (stdout, "*\n");
treeoutput ();
}
else if (good (buf))
{
if (rootword[0] == 0)
{
fprintf (stdout, "*\n"); /* perfect match */
}
else
{
fprintf (stdout, "+ %s\n", rootword);
}
}
else
{
makepossibilities (buf);
if (possibilities[0][0])
{
fprintf (stdout, "& ");
for (i = 0; i < MAXPOSSIBLE; i++)
{
if (possibilities[i][0] == 0)
break;
fprintf (stdout, "%s ", possibilities[i]);
}
fprintf (stdout, "\n");
}
else
{
fprintf (stdout, "#\n");
}
}
if (sflag)
{
stop ();
if (fflag)
{
rewind (stdout);
creat (askfilename, 0666);
}
}
}
}
/* Copy/ignore "cnt" number of characters pointed to by *cc. */
void copyout (char **cc, int cnt)
{
while (--cnt >= 0)
{
if (*(*cc) == 0)
break;
if (!lflag)
putc (*(*cc), outfile);
(*cc)++;
}
}
void lookharder (char *string)
{
char cmd[150], grepstr[100];
register char *g, *s;
g = grepstr;
for (s = string; *s != '\0'; s++)
if (*s == '*')
{
*g++ = '.';
*g++ = '*';
}
else
*g++ = *s;
*g = '\0';
if (grepstr[0])
regex_dict_lookup (cmd, grepstr);
}
void regex_dict_lookup (char *cmd, char *grepstr)
{
char *do_regex_lookup ();
char *rval;
int whence = 0;
int quit = 0;
int count = 0;
sprintf (cmd, "^%s$", grepstr);
while (!quit && (rval = do_regex_lookup (cmd, whence++)) != NULL)
{
int ch;
printcon ("%s\n", rval);;
if ((count++ % (li - 1)) == 0)
{
inverse ();
printcon ("-- more --");
normal ();
if ((ch = getccon ()) == 'q' || ch == 'Q' || ch == 'x' || ch == 'X')
quit = 1;
printcon ("\r \r");
}
}
if (rval == NULL)
{
inverse ();
printcon ("--eow--");
normal ();
getccon ();
}
}